home *** CD-ROM | disk | FTP | other *** search
- /* client.c
- *
- * code to connect to the server and call other functions to run
- * the game
- */
- #include "net3d.h"
-
- static void displayhelp(char *);
-
- bool singlep=false; /* is this a net-game? */
- char *pnames[MAX_PLAYERS]; /* names of all players */
- int sock; /* connection to server */
-
- int main(int argc, char **argv)
- {
- char name[100]=""; /* this player's name */
- struct object *ohead=NULL; /* in-game object list */
- struct vehicle *vhead=NULL; /* in-game vehicle list */
- struct map mp; /* game world terrain details */
- int number; /* client's player number */
- struct vehicle *drive; /* vehicle client is driving */
- bool alive; /* is this player still alive */
- double ltime; /* time at last check of fps */
- #if DISPLAYFPS
- int frm=0; /* frames drawn */
- #endif
- struct view vw; /* player's 3d viewpoint */
- int vmode=4; /* view of player's vehicle */
- struct vehicle *pvehicles[MAX_PLAYERS]; /* vehicles players drive */
- int plcount; /* number of people playing */
- double servertime=0.0; /* game time from server */
- bool winner=false; /* has someone won? */
- FILE *dotfp; /* fp for .surrealrc file */
- char dotsurpath[80]; /* file path to .surrealrc */
- int drvid; /* vid of current vehicle */
- struct point zpoint={0,0,0}; /* constant 0,0,0 point */
- int finalcountdown = 100; /* after death, the number of frames
- * until exit */
- char currentdir[100]; /* path to .v file in current dir */
- char net3ddir[100]; /* path to .v file in NET3D_DIR */
-
- int i; /* scratch */
- struct vehicle *vpos;
- FILE *tfp;
-
- /* initialize the default map.
- */
- mp.ht = mp.gr = NULL; /* No hills by default */
- mp.map_w = mp.map_h = 0;
- mp.size = mp.scale = 0.0;
- mp.lookout.x = 0; mp.lookout.y = 0; mp.lookout.z = 0;
- mp.rfade = 0; mp.gfade = 0; mp.bfade = 0; /* fade to black */
- mp.tcol = mp.gcol = 2; /* green hills & ground */
- mp.skycol = 32; /* black sky */
- mp.ground = True; /* ground does exist */
- mp.stars = NULL; mp.scount = 0; /* no stars */
-
- /* Display user help.
- */
- if (argc == 1) {
- printf("usage : Single player : %s <vehicle files>\n",argv[0]);
- printf(" Network game : %s <server> <player name>\n",argv[0]);
- printf(" Help : %s -help\n",argv[0]);
- exit(0);
- }
- if (!strcmp(argv[1],"-help")) {
- displayhelp(argv[0]);
- exit(0);
- }
-
- /* setup sin and cos caches */
- initcaches();
-
- /* We want children automatically reaped by default */
- signal(SIGCHLD,SIG_IGN);
-
- /* read key configuration file.
- */
- sprintf(dotsurpath,"%s/%s",getenv("HOME"),KEYFILE);
- if ((dotfp = fopen(dotsurpath,"r"))) {
- readkeyfile(dotfp);
- fclose(dotfp);
- }
-
- readextravehicles();
-
- /* Look for a file named by the first command line argument, in the current
- * directory and NET3D_DIR. If it exists, then this is a single player game.
- * If not, then the first command line argument is the name of the server,
- * and this is a multi-player game.
- */
- sprintf(currentdir,"%s",argv[1]);
- sprintf(net3ddir,"%s/%s",NET3D_DIR,argv[1]);
- if ((tfp = fopen(currentdir,"r")) || (tfp = fopen(net3ddir,"r"))) {
- /* using single player mode.
- */
- fclose(tfp);
- singlep=true;
- /* read map and vehicle files.
- */
- for(i=1; i<argc; i++) {
- int pifd;
- struct stat dummy;
-
- /* look for the vehicle file in the current directory, or
- * if not found, in the directory defined by NET3D_DIR.
- */
- sprintf(currentdir,"%s",argv[i]);
- sprintf(net3ddir,"%s/%s",NET3D_DIR,argv[i]);
- if (stat(currentdir,&dummy) != -1) {
- pifd=pipethrough(CPPPATH,currentdir);
- readfile(&ohead,&vhead,pifd,&mp);
- close(pifd);
- printf("done reading %s\n",currentdir);
- }
- else if (stat(net3ddir,&dummy) != -1) {
- pifd=pipethrough(CPPPATH,net3ddir);
- readfile(&ohead,&vhead,pifd,&mp);
- close(pifd);
- printf("done reading %s\n",net3ddir);
- }
- else {
- printf("file %s not found!\n",argv[i]);
- exit(0);
- }
- }
-
- /* check for lack of vehicles */
- if (vhead == NULL) {
- printf("No vehicles found!\n");
- exit(1);
- }
-
- /* set up the things usually got from the server */
- plcount=1;
- pnames[0]="Solo";
- makemap(&ohead,&mp);
- number=0;
- pvehicles[0]=vhead;
-
- /* put the initial game time into the pipe */
- sprintf(fakepipe,"%f\n",gametime());
- }
- else {
- char *ver;
-
- /* multi-player mode */
- sock=OpenSend(argv[1]);
- printf("Connected to server\n");
-
- /* check version */
- ver = ngets(sock);
- if (strcmp(ver,NET3D_VERSION)) {
- nprintf(sock,"%s\n",VERSION_ERROR);
- close(sock);
- printf("Rejected by server! This client is version %s,"
- " but the server is version %s\n",NET3D_VERSION,
- ver);
- exit(1);
- }
-
- if (argc > 2) {
- /* if a name is given, use it */
- int i;
-
- for(i=2; i<argc; i++) {
- strcat(name,argv[i]);
- strcat(name," ");
- }
- }
- else {
- /* Try to get the user's name from $LOGNAME, $USER or
- * cuserid().
- */
- char *env_logname, *env_user;
-
- env_logname = getenv("LOGNAME");
- env_user = getenv("USER");
- if (env_logname)
- strcpy(name,env_logname);
- else if (env_user)
- strcpy(name,env_user);
- else
- cuserid(name);
- }
- /* send player's name to the server */
- nprintf(sock,"%s\n",name);
-
- /* read the pre-processed vehicle files from the server, for reading
- * into the object and vehicle lists.
- */
- readfile(&ohead,&vhead,sock,&mp);
- printf("done reading vehicles\n");
-
- /* create the map polygons from the map array */
- makemap(&ohead,&mp);
-
- /* find player number, and from it the vehicle to drive */
- number=atoi(ngets(sock));
- if (number==-1) {
- printf("no vehicles available :(\n");
- shutdown(sock,2);
- close(sock);
- exit(2);
- }
-
- /* read true number of players from server, and from this determine
- * which player controls which vehicle
- */
- plcount=atoi(ngets(sock));
- vpos=vhead;
- for(i=0; i<plcount; i++) {
- pvehicles[i] = vpos;
- vpos->owner = o_network;
- vpos->pnum = i;
- vpos = vpos->next;
- }
-
- /* read names of all players from the server */
- for(i=0; i<plcount; i++) {
- pnames[i]=strdupe(ngets(sock));
- printf("player %d is %s\n",i,pnames[i]);
- }
- }
-
- /* display some useful info to the player */
- worldinfo(vhead,ohead);
- printcontrols();
-
- drive=pvehicles[number];
- drive->pnum = number;
- printf("You are player %d, driving vehicle %s\n",number,drive->code);
-
- /* setup 3-d world */
- drive->owner=o_player;
- drvid = drive->vid;
- alive=true;
- initX(&mp, argc, argv);
- initmightsaves(ohead);
- initmightsaves(eohead);
- readicons();
- playertype = findbycode(evhead,"player")->type;
-
- /* set up initial viewing parameters */
- vw.d=EYE_DISTANCE;
- createcamera(drive,&vw,vmode,&mp,vhead);
- vw.last.n = vw.last.u = vw.last.v = zpoint;
- vw.last.vrp = vw.vrp;
- vw.last.vmode = 0;
- init3d(&mp,&vw);
- ltime=gametime();
- calcbboxes(vhead);
-
- /* register functions to be called on break */
- if (!singlep) {
- signal(SIGINT,termhandler);
- signal(SIGTERM,termhandler);
- XSetIOErrorHandler(xerrorhandler);
- }
-
- /* play the game */
- while(1) {
- if (alive) {
- /* only re-calculate the view if the player still
- * lives. once dead, the viewpoint lingers at the
- * place of death indefinately :)
- */
- createcamera(drive,&vw,vmode,&mp,vhead);
- }
-
- /* seed the random number generator with a time from
- * the server, to make sure all clients are in sync.
- */
- srand(((int)servertime)*1000);
-
- /* draw the 3-d world, and move vehicles in it appropriately,
- * but only on the second time around the loop, after a time
- * has been read from the server
- */
- if (servertime) {
- cyclefire(servertime);
- worldtoview(&vw,ohead,drive,vmode);
- ohead=depthsort(ohead,&vw);
- render(&vw,ohead,drive,vmode,&mp);
-
- /* Only draw the radar and info if the player is in the
- * cockpit of a vehicle */
- if (vmode==4 || vmode==6) {
- drawradar(vhead,drive);
- drawinfo(drive);
- }
- if (alive && drive) {
- drawvmode(vmode,drive);
- drawbuildicons();
- }
- drawextras(drive,winner);
- controlvehicles(&vhead,&ohead);
- movevehicles(&vhead,&ohead,&mp,servertime);
- growtrees(&vhead,&ohead);
- }
-
- if (alive && !drive->alive) {
- /* either the player is dead, or they have transfered
- * to another vehicle.
- */
- if (drive->transfer != -1) {
- /* they have transferred */
- struct vehicle *v;
-
- /* v = vehicle transferred to */
- v = findbyvid(vhead,drive->transfer);
- if (!v) {
- printf("vid for transfer not found!\n");
- exit(20);
- }
- /* free the old vehicle, and change the drive
- * pointer and drvid to indicate that a new vehicle
- * is now being driven.
- */
- v->owner = drive->owner;
- free(drive);
- drive = v;
- drvid = drive->vid;
- }
- else {
- /* player has just died. Tell the server, and
- * clean up their vehicle */
- alive=false;
- printf("dead\n");
- free(drive);
- drive=NULL;
- if (!singlep) {
- /* tell server this client is dead */
- nprintf(sock,"d");
- }
- }
- }
-
- #if DISPLAYFPS
- /* calculate frames/second */
- frm++;
- if (frm==100 && servertime) {
- double ntime; /* current time */
-
- ntime=servertime;
- printf("%lf fps\n",100.0/(ntime-ltime));
- ltime=ntime;
- frm=0;
- }
- #endif
-
- #if DISPLAYCACHEINFO
- /* display efficiency of map caching */
- if (frm == 0) {
- double hitpercent;
-
- if (mappointsdone) {
- hitpercent = (mapcachehits/(double)mappointsdone) * 100;
- printf("map cache %.2lf ",hitpercent);
- mapcachehits = mappointsdone = 0.0;
- }
-
- if (sincalls) {
- hitpercent = (sincachehits / (double)sincalls) * 100;
- printf("sin cache %.2lf",hitpercent);
- sincachehits = sincalls = 0.0;
- }
-
- printf("\n");
- }
- #endif
-
- /* Read commands and the new game time from the server */
- if (singlep)
- servertime=readnet(&vhead,&ohead,&winner,&drvid);
- else
- servertime=readnet(&vhead,&ohead,&winner,&drvid);
-
- /* check for a change in the player's vehicle, after they
- * have ejected.
- */
- if (drive && drvid != drive->vid) {
- /* a new vehicle! search the list for the vehicle
- * structure matching the new vid.
- */
- drive = findbyvid(vhead,drvid);
- if (!drive) {
- printf( "The vid for the ejected player doesn't\n"
- "match any in the list!!!\n");
- exit(20);
- }
- }
-
- /* If the player is still alive, call readkeys() as normal,
- * otherwise pass in a NULL to indicate that the player is
- * dead.
- */
- if (alive) {
- if (singlep)
- readkeys(&vmode,drive,vhead,servertime);
- else
- readkeys(&vmode,drive,vhead,servertime);
- }
- else {
- if (singlep)
- readkeys(&vmode,NULL,vhead,servertime);
- else
- readkeys(&vmode,NULL,vhead,servertime);
- }
-
- /* After death, start the final countdown and exit when it REAches 0.
- */
- if (!alive && singlep)
- if (!(finalcountdown--))
- exit(0);
- }
-
- /* close connection to the server */
- if (!singlep) {
- shutdown(sock,2);
- close(sock);
- }
- return(0);
- }
-
- static void displayhelp(char *cn)
- {
- printf(
- "net3d client help\n"
- "-----------------\n"
- "Single player mode : To start net3d in single-player mode, type :\n"
- " %s <vehicle file> <vehicle file> ... \n"
- " Vehicle files have the extension .v, and at least\n"
- " one must be given. If multiple vehicle files are\n"
- " listed, then the last vehicle in the last file will\n"
- " be the one driven in the game.\n"
- "\n"
- " For example, if you typed %s map.v tank.v\n"
- " then you would be controlling a tank, among scenery\n"
- " and other vehicles from map.v\n"
- "\n"
- "\n"
- "Multiplayer mode : To start net3d in multi-player (networked) mode, type :\n"
- " %s <server> <name>\n"
- " <server> is the machine on which the net3d server is\n"
- " running, and <name> is the name identifying you in\n"
- " the game. The vehicle you control in the game is\n"
- " determined by the server, which assigns a vehicle to\n"
- " each player.\n"
- ,cn,cn,cn);
- }
-
-